package com.dreamwhale.machinery.wxConfig;


import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.dreamwhale.machinery.adviceException.DragonException;
import com.dreamwhale.machinery.config.DataResult;
import com.dreamwhale.machinery.config.HttpRequest;
import com.dreamwhale.machinery.dao.*;
import com.dreamwhale.machinery.entity.*;
import com.dreamwhale.machinery.goods.controller.UserLoginController;
import com.dreamwhale.machinery.goods.entity.YxStoreCart;
import com.dreamwhale.machinery.goods.entity.YxStoreOrder;
import com.dreamwhale.machinery.goods.mapper.YxStoreOrderMapper;
import com.dreamwhale.machinery.goods.service.YxStoreCartService;
import com.dreamwhale.machinery.goods.service.YxStoreOrderService;
import com.dreamwhale.machinery.pay.weChat.server.WeChatPayServer;
import com.dreamwhale.machinery.pay.weChat.utils.WxNotifyParam;
import com.dreamwhale.machinery.pay.weChat.utils.XMLUtil;
import com.dreamwhale.machinery.service.UserApplyService;
import com.dreamwhale.machinery.service.YxStoreProductService;
import com.dreamwhale.machinery.user.entity.UserShop;
import com.dreamwhale.machinery.user.entity.YxUser;
import com.dreamwhale.machinery.user.entity.YxUserAddress;
import com.dreamwhale.machinery.user.mapper.UserShopMapper;
import com.dreamwhale.machinery.user.mapper.YxUserMapper;
import com.dreamwhale.machinery.user.service.YxUserAddressService;
import com.dreamwhale.machinery.utils.WorkIdUtils;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 店铺消息分享记录表 前端控制器
 * </p>
 *
 * @author Author
 * @since 2020-02-03
 */
@RestController
@RequestMapping("/pay")
public class WxChantController {


    @Resource
    private YxStoreOrderMapper yxStoreOrderMapper;

    @Resource
    private WeChatPayServer weChatPayServer;

    @Resource
    private UserApplyMapper userApplyMapper;

    @Resource
    private DictDetailMapper dictDetailMapper;

    @Resource
    private YxUserMapper yxUserMapper;

    @Resource
    private VipInfoMapper vipInfoMapper;

    @Resource
    private VipUserInfoMapper vipUserInfoMapper;

    @Resource
    private YxStoreCartService yxStoreCartService;

    @Resource
    private YxStoreProductService yxStoreProductService;


    @Resource
    private YxStoreProductAttrValueMapper yxStoreProductAttrValueMapper;

    @Resource
    private YxUserAddressService yxUserAddressService;

    @Resource
    private YxStoreOrderService yxStoreOrderService;

    @Resource
    private UserApplyService userApplyService;

    @Resource
    private UserLoginController userLoginController;

    @Resource
    private UserShopMapper userShopMapper;

    /**
     * 订单支付
     *
     * @param
     * @return
     */
    @RequestMapping("/payMiniWeChatOrder")
    @Transactional
    public DataResult payMiniWeChat(HttpServletRequest request, YxStoreCart yxStoreCart, Integer addrId) {
        try {
            //首先加入购物车
            yxStoreCart.setAddTime(LocalDateTime.now());
            if (yxStoreCartService.save(yxStoreCart)) {
//            List<Integer> longs = Collections.singletonList(yxStoreCart.getId().intValue());
                return payMiniWeChatTrolleyOrder(request, yxStoreCart.getId().toString(), addrId);
            }
            return new DataResult(300, "订单创建失败", null);
        } catch (Exception e) {
            e.printStackTrace();
            return DataResult.build(300, "支付失败");
        }

    }


    /**
     * 小程序微信支付
     *
     * @param request
     * @param payOrderId //订单ID
     * @param openid     //用户的OPENid
     * @return
     */
    @RequestMapping(value = "/wxPay", method = RequestMethod.POST)
    public DataResult wxPay(HttpServletRequest request, String payOrderId, String backJsonInfo, String openid) {
        System.out.println("======下程序微信支付开始" + payOrderId + "==============================");
        try {
            //生成的随机字符串
            String nonce_str = getRandomStringByLength(32);
            //商品名称
            String body = "测试商品名称";
            //获取客户端的ip地址
            String spbill_create_ip = getIpAddr(request);
            //查询订单
            //查询订单
            QueryWrapper<YxStoreOrder> yxStoreOrderQueryWrapper = new QueryWrapper<>();
            yxStoreOrderQueryWrapper.eq("order_id", payOrderId);
            YxStoreOrder yxStoreOrder = yxStoreOrderMapper.selectOne(yxStoreOrderQueryWrapper);
            //获取订单金额
            Double msdToPrice = yxStoreOrder.getTotalPrice().multiply(BigDecimal.valueOf(100)).doubleValue();
            Integer intValue = msdToPrice.intValue();

            //组装参数，用户生成统一下单接口的签名
            Map<String, String> packageParams = new HashMap<>();
            packageParams.put("appid", WechatConfig.appid);
            packageParams.put("mch_id", WechatConfig.mch_id);
            packageParams.put("nonce_str", nonce_str);
            packageParams.put("body", body);
            packageParams.put("out_trade_no", payOrderId + "");//商户订单号,自己的订单ID
            packageParams.put("total_fee", intValue.toString());//支付金额，这边需要转成字符串类型，否则后面的签名会失败
            packageParams.put("spbill_create_ip", spbill_create_ip);
            packageParams.put("notify_url", WechatConfig.notify_url);//支付成功后的回调地址
            packageParams.put("trade_type", WechatConfig.TRADETYPE);//支付方式
            packageParams.put("openid", openid + "");//用户的openID，自己获取
            packageParams.put("attach", backJsonInfo);
            String prestr = PayUtil.createLinkString(packageParams); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串

            //MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
            String mysign = PayUtil.sign(prestr, WechatConfig.key, "utf-8").toUpperCase();

            //拼接统一下单接口使用的xml数据，要将上一步生成的签名一起拼接进去
            String xml = "<xml>" + "<appid>" + WechatConfig.appid + "</appid>"
                    + "<body><![CDATA[" + body + "]]></body>"
                    + "<mch_id>" + WechatConfig.mch_id + "</mch_id>"
                    + "<nonce_str>" + nonce_str + "</nonce_str>"
                    + "<notify_url>" + WechatConfig.notify_url + "</notify_url>"
                    + "<openid>" + openid + "</openid>"
                    + "<out_trade_no>" + payOrderId + "</out_trade_no>"
                    + "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>"
                    + "<total_fee>" + intValue + "</total_fee>"//支付的金额，单位：分
                    + "<trade_type>" + WechatConfig.TRADETYPE + "</trade_type>"
                    + "<attach>" + backJsonInfo + "</attach>"
                    + "<sign>" + mysign + "</sign>"
                    + "</xml>";
            System.out.println(xml);
            //调用统一下单接口，并接受返回的结果
            String result = PayUtil.httpRequest(WechatConfig.pay_url, "POST", xml);

            System.out.println("调试模式_统一下单接口 返回XML数据：" + result);
            // 将解析结果存储在HashMap中
            Map map = PayUtil.doXMLParse(result);

            String return_code = (String) map.get("return_code");//返回状态码
            String result_code = (String) map.get("result_code");//返回状态码

            Map<String, Object> response = new HashMap<String, Object>();//返回给小程序端需要的参数
            if (return_code.equals("SUCCESS") && return_code.equals(result_code)) {
                String prepay_id = (String) map.get("prepay_id");//返回的预付单信息
                response.put("nonceStr", nonce_str);
                response.put("package", "prepay_id=" + prepay_id);
                Long timeStamp = System.currentTimeMillis() / 1000;
                response.put("timeStamp", timeStamp + "");//这边要将返回的时间戳转化成字符串，不然小程序端调用wx.requestPayment方法会报签名错误
                //拼接签名需要的参数
                String stringSignTemp = "appId=" + WechatConfig.appid + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
                //再次签名，这个签名用于小程序端调用wx.requesetPayment方法
                String paySign = PayUtil.sign(stringSignTemp, WechatConfig.key, "utf-8").toUpperCase();

                response.put("paySign", paySign);
            }

            response.put("appid", WechatConfig.appid);
            response.put("payOrderId", payOrderId);
            System.out.println(response);
            System.out.println("======下程序微信支付结束" + payOrderId + "==============================");
            return DataResult.ok(response);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("======下程序微信支付结束" + payOrderId + "==============================");
        return null;

    }


    //1.订单支付/2。机修学堂//3.vip这里是支付回调接口，微信支付成功后会自动调用
    @RequestMapping(value = "/wxNotify", method = RequestMethod.POST)
    public void wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        System.out.println("========小程序支付回调开始===========================");
        BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        br.close();
        //sb为微信返回的xml
        String notityXml = sb.toString();
        String resXml = "";

        Map map = PayUtil.doXMLParse(notityXml);
        System.out.println("订单号码" + (String) map.get("out_trade_no"));
        String returnCode = (String) map.get("return_code");
        System.out.println(returnCode + "是否是success");
         if ("SUCCESS".equals(returnCode)) {
            System.out.println("进入sucess");
            //验证签名是否正确
            Map<String, String> validParams = PayUtil.paraFilter(map);  //回调验签时需要去除sign和空值参数
            String prestr = PayUtil.createLinkString(validParams);
            System.out.println("根据微信官网的介绍，236" + prestr);
            System.out.println((String) map.get("sign"));
            System.out.println(WechatConfig.key);
            //根据微信官网的介绍，此处不仅对回调的参数进行验签，还需要对返回的金额与系统订单的金额进行比对等
            //判断验证为false，具体原因不明，官方网站效验为true，暂且保留
            /*  if (PayUtil.verify(prestr, (String) map.get("sign"), WechatConfig.key, "utf-8")) {*/
            System.out.println("进入根据微信官网的介绍");
            /**此处添加自己的业务逻辑代码start**/
            //获取订单号
            //获取订单号


            System.out.println("=====================回调=======================");
            if (CollectionUtils.isEmpty(validParams) || !validParams.get("return_code").equals("SUCCESS")) {

                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
            } else {
                // ------------------------------
                // 处理业务开始
                // ------------------------------

                String out_trade_no = validParams.get("out_trade_no");
                String attach = validParams.get("attach");
                String payType = JSON.parseObject(attach).get("payType").toString();
                String userId = JSON.parseObject(attach).get("userId").toString();

                switch (Integer.parseInt(payType)) {
                    case 0:
                        break;
                    case 1:
                        YxStoreOrder yxStoreOrder = yxStoreOrderMapper.selectOne(new QueryWrapper<YxStoreOrder>().eq("order_id", out_trade_no));
                        yxStoreOrder.setPaid(true);
                        yxStoreOrder.setPayTime(LocalDateTime.now());
                        yxStoreOrderMapper.updateById(yxStoreOrder);
                        System.out.println("订单信息");
                        break;
                    case 2:
                        UserApply applyOrder = userApplyMapper.selectById(new QueryWrapper<UserApply>().eq("apply_order_id", out_trade_no));
                        applyOrder.setApplyPayTime(LocalDateTime.now());
                        userApplyMapper.updateById(applyOrder);
                        Object pid1 = JSON.parseObject(attach).get("pid");
                        //给邀请的人一个奖励
                        if (pid1 != null) {
                            DictDetail dictDetail = dictDetailMapper.selectOne(new QueryWrapper<DictDetail>().eq("label", "applyAwards"));
                            BigDecimal decimal = BigDecimal.valueOf(Integer.parseInt(dictDetail.getValue()));
                            Integer pid = Integer.parseInt(pid1.toString());
                            VipUserInfo userInfo = vipUserInfoMapper.selectById(pid);
                            userInfo.setPayMoney(userInfo.getPayMoney().add(decimal));
                            vipUserInfoMapper.updateById(userInfo);
                        }
                        break;
                    case 3:
                        VipUserInfo vipUserInfo = vipUserInfoMapper.selectById(out_trade_no);
                        vipUserInfo.setPayTime(LocalDateTime.now());
                        vipUserInfoMapper.updateById(vipUserInfo);
                        break;
                }

                //注意要判断微信支付重复回调，支付成功后微信会重复的进行回调

                /**此处添加自己的业务逻辑代码end**/
                //通知微信服务器已经支付成功
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
//            }
            }

        }

        BufferedOutputStream out = new BufferedOutputStream(
                response.getOutputStream());
        out.write(resXml.getBytes());
        out.flush();
        out.close();
        System.out.println("========小程序支付回调结束===========================");
    }


    /**
     * 机修学堂支付
     *
     * @param
     * @return
     */
    @RequestMapping("/payMiniWeChatOfficial")
    @Transactional
    public DataResult payMiniWeChatOfficial(String name, String phone, @RequestParam(defaultValue = "") Integer pid, @RequestParam(defaultValue = "") String code, @RequestParam(defaultValue = "") String userId, HttpServletRequest request) {
        try {
            DictDetail dictDetail = dictDetailMapper.selectOne(new QueryWrapper<DictDetail>().eq("label", "apply"));
            UserApply userApply = new UserApply();
            String orderId = WorkIdUtils.generateOrderId();
            userApply.setApplyCreateTime(LocalDateTime.now());
            userApply.setApplyOrderId(orderId);
            userApply.setApplyName(name);
            userApply.setApplyPhone(phone);
            userApply.setApplyMoney(BigDecimal.valueOf(Double.parseDouble(dictDetail.getValue())));
            if (userApplyService.save(userApply)) {
                UserApply userApplys = userApplyMapper.selectById(orderId);
                HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
                objectObjectHashMap.put("payType", 2);
                objectObjectHashMap.put("pid", pid);

                if (StringUtils.isNotBlank(userId)) {
                    //查询openid
                    QueryWrapper<YxUser> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("uid", userId);
                    objectObjectHashMap.put("userId", userId);
                    YxUser yxUser = yxUserMapper.selectOne(queryWrapper);
                    return wxPayOfficial(request, userApplys.getApplyOrderId(), JSON.toJSONString(objectObjectHashMap), yxUser.getOpenId());
                } else {
                    objectObjectHashMap.put("userId", 0);
                 /*   DataResult weOpenIDCodes = userLoginController.getWeOpenIDCodes(code);
                    String s = JSON.toJSONString(weOpenIDCodes.getData());*/
                    Map map = new HashMap();
                    //登录凭证不能为空
                    if (code == null || code.length() == 0) {
                        map.put("status", 0);
                        map.put("msg", "code 不能为空");
                        return DataResult.build(300, "code 不能为空");
                    }
                    //小程序唯一标识   (在微信小程序管理后台获取)
//            String wxspAppid = "wxa01518371f187b24";
                    String wxspAppid = "wxbc645cafc9875782";
                    //小程序的 app secret (在微信小程序管理后台获取)
//            String wxspSecret = "975f6d74c4feb75c27b066cdd5f9dd68";
                    String wxspSecret = "a643b4a2ca606e1f4df1f883899d4ddc";
                    //授权（必填）
                    String grant_type = "authorization_code";
                    //////////////// 1、向微信服务器 使用登录凭证 code 获取 session_key 和 openid ////////////////
                    //请求参数
                    String params = "appid=" + wxspAppid + "&secret=" + wxspSecret + "&js_code=" + code + "&grant_type=" + grant_type;
                    //发送请求
                    String sr = HttpRequest.sendWeOpenIdGet("https://api.weixin.qq.com/sns/jscode2session", params);
                    System.out.println("================请求地址" + sr);
                    //解析相应内容（转换成json对象）
                    JSONObject json = JSONObject.fromObject(sr);
                    System.out.println("=============" + json);
                    //获取会话密钥（session_key）
                    String session_key = json.get("session_key").toString();
                    //用户的唯一标识（openid）
                    String openid = (String) json.get("openid");
                    System.out.println("================openid" + openid);

                    Map<String, Object> maps = new HashMap<>();
                    maps.put("openid", openid);
                    maps.put("session_key", session_key);

                    return wxPayOfficial(request, userApplys.getApplyOrderId(), JSON.toJSONString(objectObjectHashMap), openid);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return DataResult.build(300, "支付失败");
        }
        return DataResult.build(300, "支付失败");
    }


    /**
     * 机修学堂支付微信支付
     *
     * @param request
     * @param payOrderId //订单ID
     * @param openid     //用户的OPENid
     * @return
     */
    @RequestMapping(value = "/wxPayOfficial", method = RequestMethod.POST)
    public DataResult wxPayOfficial(HttpServletRequest request, String payOrderId, String backJsonInfo, String openid) {
        System.out.println("======下程序微信支付开始" + payOrderId + "==============================");
        try {
            //生成的随机字符串
            String nonce_str = getRandomStringByLength(32);
            //商品名称
            String body = "测试商品名称";
            //获取客户端的ip地址
            String spbill_create_ip = getIpAddr(request);
            //查询订单
            UserApply userApply = userApplyMapper.selectById(payOrderId);
            //获取订单金额
            Double msdToPrice = userApply.getApplyMoney().multiply(BigDecimal.valueOf(100)).doubleValue();
            Integer intValue = msdToPrice.intValue();

            //组装参数，用户生成统一下单接口的签名
            Map<String, String> packageParams = new HashMap<>();
            packageParams.put("appid", WechatConfig.appid);
            packageParams.put("mch_id", WechatConfig.mch_id);
            packageParams.put("nonce_str", nonce_str);
            packageParams.put("body", body);
            packageParams.put("out_trade_no", payOrderId + "");//商户订单号,自己的订单ID
            packageParams.put("total_fee", intValue.toString());//支付金额，这边需要转成字符串类型，否则后面的签名会失败
            packageParams.put("spbill_create_ip", spbill_create_ip);
            packageParams.put("notify_url", WechatConfig.notify_url);//支付成功后的回调地址
            packageParams.put("trade_type", WechatConfig.TRADETYPE);//支付方式
            packageParams.put("openid", openid + "");//用户的openID，自己获取
            packageParams.put("attach", backJsonInfo);
            String prestr = PayUtil.createLinkString(packageParams); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串

            //MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
            String mysign = PayUtil.sign(prestr, WechatConfig.key, "utf-8").toUpperCase();

            //拼接统一下单接口使用的xml数据，要将上一步生成的签名一起拼接进去
            String xml = "<xml>" + "<appid>" + WechatConfig.appid + "</appid>"
                    + "<body><![CDATA[" + body + "]]></body>"
                    + "<mch_id>" + WechatConfig.mch_id + "</mch_id>"
                    + "<nonce_str>" + nonce_str + "</nonce_str>"
                    + "<notify_url>" + WechatConfig.notify_url + "</notify_url>"
                    + "<openid>" + openid + "</openid>"
                    + "<out_trade_no>" + payOrderId + "</out_trade_no>"
                    + "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>"
                    + "<total_fee>" + intValue + "</total_fee>"//支付的金额，单位：分
                    + "<trade_type>" + WechatConfig.TRADETYPE + "</trade_type>"
                    + "<attach>" + backJsonInfo + "</attach>"
                    + "<sign>" + mysign + "</sign>"
                    + "</xml>";
            System.out.println(xml);
            //调用统一下单接口，并接受返回的结果
            String result = PayUtil.httpRequest(WechatConfig.pay_url, "POST", xml);

            System.out.println("调试模式_统一下单接口 返回XML数据：" + result);
            // 将解析结果存储在HashMap中
            Map map = PayUtil.doXMLParse(result);

            String return_code = (String) map.get("return_code");//返回状态码
            String result_code = (String) map.get("result_code");//返回状态码

            Map<String, Object> response = new HashMap<String, Object>();//返回给小程序端需要的参数
            if (return_code.equals("SUCCESS") && return_code.equals(result_code)) {
                String prepay_id = (String) map.get("prepay_id");//返回的预付单信息
                response.put("nonceStr", nonce_str);
                response.put("package", "prepay_id=" + prepay_id);
                Long timeStamp = System.currentTimeMillis() / 1000;
                response.put("timeStamp", timeStamp + "");//这边要将返回的时间戳转化成字符串，不然小程序端调用wx.requestPayment方法会报签名错误
                //拼接签名需要的参数
                String stringSignTemp = "appId=" + WechatConfig.appid + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
                //再次签名，这个签名用于小程序端调用wx.requesetPayment方法
                String paySign = PayUtil.sign(stringSignTemp, WechatConfig.key, "utf-8").toUpperCase();

                response.put("paySign", paySign);
            }

            response.put("appid", WechatConfig.appid);
            response.put("payOrderId", payOrderId);
            System.out.println(response);
            System.out.println("======下程序微信支付结束" + payOrderId + "==============================");
            return DataResult.ok(response);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("======下程序微信支付结束" + payOrderId + "==============================");
        return null;

    }


    /**
     * vip充值
     *
     * @param
     * @return
     */
    @RequestMapping("/payMiniWeChatVip")
    @Transactional
    public DataResult payMiniWeChatVip(HttpServletRequest request, Integer vipId, Integer userId) {
        try {
            System.out.println(userId + "进入方法");
            VipInfo vipInfo = vipInfoMapper.selectById(vipId);
            if (vipInfo == null) {
                throw new DragonException("会员不存在");
            }
            BigDecimal vipPrice = vipInfo.getVipPrice();
            BigDecimal discount = BigDecimal.ZERO;
            BigDecimal payment = vipPrice.subtract(discount);

            VipUserInfo vipUserInfo1 = vipUserInfoMapper.inquiryVipExpirationTime(userId);
            LocalDateTime expirationTime = vipUserInfo1 == null ? LocalDateTime.now() : vipUserInfo1.getExpirationTime();
            VipUserInfo vipUserInfo = new VipUserInfo();
            vipUserInfo.setVid(vipId);
            vipUserInfo.setUid(userId);
            vipUserInfo.setCreateTime(LocalDateTime.now());
            vipUserInfo.setPayOrderId(IdWorker.getIdStr());
            vipUserInfo.setPayMoney(payment);
            vipUserInfo.setExpirationTime(expirationTime.compareTo(LocalDateTime.now()) > 0
                    ? expirationTime.plusMonths(vipInfo.getVipMonth())
                    : LocalDateTime.now().plusMonths(vipInfo.getVipMonth())
            );
            if (vipUserInfoMapper.insert(vipUserInfo) == 1) {

                //查询openid
                QueryWrapper<YxUser> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("uid", userId);
                YxUser yxUser = yxUserMapper.selectOne(queryWrapper);
                return wxPayVip(request, vipUserInfo.getPayOrderId(), yxUser.getOpenId());
            }
            return DataResult.build(300, "支付失败");
        } catch (Exception e) {
            e.printStackTrace();
            return DataResult.build(300, "支付失败");
        }

    }

    /**
     * vip支付微信支付
     *
     * @param request
     * @param payOrderId //订单ID
     * @param openid     //用户的OPENid
     * @return
     */
    @RequestMapping(value = "/wxPayVip", method = RequestMethod.POST)
    public DataResult wxPayVip(HttpServletRequest request, String payOrderId, String openid) {
        System.out.println("======下程序微信支付开始" + payOrderId + "==============================");
        try {
            //生成的随机字符串
            String nonce_str = getRandomStringByLength(32);
            //商品名称
            String body = "测试商品名称";
            //获取客户端的ip地址
            String spbill_create_ip = getIpAddr(request);
            //查询订单
            QueryWrapper<VipUserInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("pay_order_id", payOrderId);
            VipUserInfo vipUserInfo = vipUserInfoMapper.selectOne(queryWrapper);
            //获取订单金额
            Double msdToPrice = vipUserInfo.getPayMoney().multiply(BigDecimal.valueOf(100)).doubleValue();
            Integer intValue = msdToPrice.intValue();

            //组装参数，用户生成统一下单接口的签名
            Map<String, String> packageParams = new HashMap<>();
            packageParams.put("appid", WechatConfig.appid);
            packageParams.put("mch_id", WechatConfig.mch_id);
            packageParams.put("nonce_str", nonce_str);
            packageParams.put("body", body);
            packageParams.put("out_trade_no", payOrderId + "");//商户订单号,自己的订单ID
            packageParams.put("total_fee", intValue.toString());//支付金额，这边需要转成字符串类型，否则后面的签名会失败
            packageParams.put("spbill_create_ip", spbill_create_ip);
            packageParams.put("notify_url", WechatConfig.notify_url);//支付成功后的回调地址
            packageParams.put("trade_type", WechatConfig.TRADETYPE);//支付方式
            packageParams.put("openid", openid + "");//用户的openID，自己获取
            String prestr = PayUtil.createLinkString(packageParams); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串

            //MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
            String mysign = PayUtil.sign(prestr, WechatConfig.key, "utf-8").toUpperCase();

            //拼接统一下单接口使用的xml数据，要将上一步生成的签名一起拼接进去
            String xml = "<xml>" + "<appid>" + WechatConfig.appid + "</appid>"
                    + "<body><![CDATA[" + body + "]]></body>"
                    + "<mch_id>" + WechatConfig.mch_id + "</mch_id>"
                    + "<nonce_str>" + nonce_str + "</nonce_str>"
                    + "<notify_url>" + WechatConfig.notify_url + "</notify_url>"
                    + "<openid>" + openid + "</openid>"
                    + "<out_trade_no>" + payOrderId + "</out_trade_no>"
                    + "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>"
                    + "<total_fee>" + intValue + "</total_fee>"//支付的金额，单位：分
                    + "<trade_type>" + WechatConfig.TRADETYPE + "</trade_type>"
                    + "<sign>" + mysign + "</sign>"
                    + "</xml>";
            System.out.println(xml);
            //调用统一下单接口，并接受返回的结果
            String result = PayUtil.httpRequest(WechatConfig.pay_url, "POST", xml);

            System.out.println("调试模式_统一下单接口 返回XML数据：" + result);
            // 将解析结果存储在HashMap中
            Map map = PayUtil.doXMLParse(result);

            String return_code = (String) map.get("return_code");//返回状态码
            String result_code = (String) map.get("result_code");//返回状态码

            Map<String, Object> response = new HashMap<String, Object>();//返回给小程序端需要的参数
            if (return_code.equals("SUCCESS") && return_code.equals(result_code)) {
                String prepay_id = (String) map.get("prepay_id");//返回的预付单信息
                response.put("nonceStr", nonce_str);
                response.put("package", "prepay_id=" + prepay_id);
                Long timeStamp = System.currentTimeMillis() / 1000;
                response.put("timeStamp", timeStamp + "");//这边要将返回的时间戳转化成字符串，不然小程序端调用wx.requestPayment方法会报签名错误
                //拼接签名需要的参数
                String stringSignTemp = "appId=" + WechatConfig.appid + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
                //再次签名，这个签名用于小程序端调用wx.requesetPayment方法
                String paySign = PayUtil.sign(stringSignTemp, WechatConfig.key, "utf-8").toUpperCase();

                response.put("paySign", paySign);
            }

            response.put("appid", WechatConfig.appid);
            response.put("payOrderId", payOrderId);
            System.out.println(response);
            System.out.println("======下程序微信支付结束" + payOrderId + "==============================");
            return DataResult.ok(response);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("======下程序微信支付结束" + payOrderId + "==============================");
        return null;

    }


    /**
     * 点击购物车支付
     *
     * @param request
     * @param trolleyIds
     * @param addrId
     * @return
     */
    @RequestMapping(value = "/payMiniWeChatTrolleyOrder", method = RequestMethod.POST)
    @Transactional
    public DataResult payMiniWeChatTrolleyOrder(HttpServletRequest request, String trolleyIds, Integer addrId) {
        Integer userId = Integer.parseInt(request.getAttribute("userId").toString());
        YxStoreOrder yxStoreOrder = new YxStoreOrder();
        yxStoreOrder.setAddTime(LocalDateTime.now());
        yxStoreOrder.setTotalPrice(BigDecimal.ZERO);
        yxStoreOrder.setTotalNum(0);
        yxStoreOrder.setFreightPrice(BigDecimal.ZERO);
        String[] a = trolleyIds.split(",");
        for (String string : a) {
            YxStoreCart yxStoreCart = yxStoreCartService.getById(string);
            YxStoreProduct storeProduct = yxStoreProductService.getById(yxStoreCart.getProductId());
            YxStoreProductAttrValue yxStoreProductAttrValue = yxStoreProductAttrValueMapper.
                    selectOne(new QueryWrapper<YxStoreProductAttrValue>().eq("product_id", yxStoreCart.getProductId())
                            .eq("suk", yxStoreCart.getProductAttrUnique()));
            if (storeProduct.getPostage() == null) {
                storeProduct.setPostage(BigDecimal.ZERO);
            }
            BigDecimal multiply = yxStoreProductAttrValue.getPrice().multiply(BigDecimal.valueOf(yxStoreCart.getCartNum()));
            BigDecimal total = multiply.add(storeProduct.getPostage());
            yxStoreOrder.setTotalPrice(yxStoreOrder.getTotalPrice().add(total));
            yxStoreOrder.setTotalNum(yxStoreOrder.getTotalNum() + yxStoreCart.getCartNum());

            yxStoreOrder.setFreightPrice(yxStoreOrder.getFreightPrice().add(storeProduct.getPostage()));
            yxStoreOrder.setUid(yxStoreCart.getUid());
            //商戶
            QueryWrapper<UserShop> userShopQueryWrapper = new QueryWrapper<>();
            userShopQueryWrapper.eq("id", storeProduct.getMerId());
            UserShop userShop = userShopMapper.selectOne(userShopQueryWrapper);
            yxStoreOrder.setMerId(userShop.getId().intValue());

        }
        yxStoreOrder.setCartId(trolleyIds);
        String orderId = WorkIdUtils.generateOrderId();
        yxStoreOrder.setOrderId(orderId);
        YxUserAddress userAddressInfo = yxUserAddressService.getById(addrId);
        yxStoreOrder.setRealName(userAddressInfo.getRealName());
        yxStoreOrder.setUserPhone(userAddressInfo.getPhone());
        yxStoreOrder.setUserAddress(JSON.toJSONString(userAddressInfo));
        if (yxStoreOrderService.save(yxStoreOrder)) {
            HashMap<String, Object> resultMap = new HashMap<>();
            resultMap.put("orderInfo", yxStoreOrderService.getById(yxStoreOrder.getId()));
            String cartId = yxStoreOrder.getCartId();
            //return weChatPayServer.order(yxStoreOrder.getId().toString(), yxStoreOrder.getUid(),null,null);
            HashMap<Object, Object> objectObjectHashMap = new HashMap<>();


            //查询openid
            QueryWrapper<YxUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("uid", userId);
            YxUser yxUser = yxUserMapper.selectOne(queryWrapper);

            objectObjectHashMap.put("payType", 1);
            objectObjectHashMap.put("userId", userId);

            return wxPayTrolleyOrder(request, yxStoreOrder.getOrderId(), JSON.toJSONString(objectObjectHashMap), yxUser.getOpenId());
        }
        return DataResult.build(300, "支付失败");
    }


    /**
     * 购物车微信支付
     *
     * @param request
     * @param payOrderId //订单ID
     * @param openid     //用户的OPENid
     * @return
     */
    @RequestMapping(value = "/wxPayTrolleyOrder", method = RequestMethod.POST)
    public DataResult wxPayTrolleyOrder(HttpServletRequest request, String payOrderId, String backJsonInfo, String openid) {
        System.out.println("======下程序微信支付开始" + payOrderId + "==============================");
        try {
            //生成的随机字符串
            String nonce_str = getRandomStringByLength(32);
            //商品名称
            String body = "测试商品名称";
            //获取客户端的ip地址
            String spbill_create_ip = getIpAddr(request);
            //查询订单
            QueryWrapper<YxStoreOrder> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("order_id", payOrderId);
            YxStoreOrder yxStoreOrder = yxStoreOrderMapper.selectOne(queryWrapper);
            //获取订单金额
            Double msdToPrice = yxStoreOrder.getTotalPrice().multiply(BigDecimal.valueOf(100)).doubleValue();
            Integer intValue = msdToPrice.intValue();

            //组装参数，用户生成统一下单接口的签名
            Map<String, String> packageParams = new HashMap<>();
            packageParams.put("appid", WechatConfig.appid);
            packageParams.put("mch_id", WechatConfig.mch_id);
            packageParams.put("nonce_str", nonce_str);
            packageParams.put("body", body);
            packageParams.put("out_trade_no", payOrderId + "");//商户订单号,自己的订单ID
            packageParams.put("total_fee", intValue.toString());//支付金额，这边需要转成字符串类型，否则后面的签名会失败
            packageParams.put("spbill_create_ip", spbill_create_ip);
            packageParams.put("notify_url", WechatConfig.notify_url);//支付成功后的回调地址
            packageParams.put("trade_type", WechatConfig.TRADETYPE);//支付方式
            packageParams.put("openid", openid + "");//用户的openID，自己获取
            packageParams.put("attach", backJsonInfo);
            String prestr = PayUtil.createLinkString(packageParams); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串

            //MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
            String mysign = PayUtil.sign(prestr, WechatConfig.key, "utf-8").toUpperCase();

            //拼接统一下单接口使用的xml数据，要将上一步生成的签名一起拼接进去
            String xml = "<xml>" + "<appid>" + WechatConfig.appid + "</appid>"
                    + "<body><![CDATA[" + body + "]]></body>"
                    + "<mch_id>" + WechatConfig.mch_id + "</mch_id>"
                    + "<nonce_str>" + nonce_str + "</nonce_str>"
                    + "<notify_url>" + WechatConfig.notify_url + "</notify_url>"
                    + "<openid>" + openid + "</openid>"
                    + "<out_trade_no>" + payOrderId + "</out_trade_no>"
                    + "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>"
                    + "<total_fee>" + intValue + "</total_fee>"//支付的金额，单位：分
                    + "<trade_type>" + WechatConfig.TRADETYPE + "</trade_type>"
                    + "<attach>" + backJsonInfo + "</attach>"
                    + "<sign>" + mysign + "</sign>"
                    + "</xml>";
            System.out.println(xml);
            //调用统一下单接口，并接受返回的结果
            String result = PayUtil.httpRequest(WechatConfig.pay_url, "POST", xml);

            System.out.println("调试模式_统一下单接口 返回XML数据：" + result);
            // 将解析结果存储在HashMap中
            Map map = PayUtil.doXMLParse(result);

            String return_code = (String) map.get("return_code");//返回状态码
            String result_code = (String) map.get("result_code");//返回状态码

            Map<String, Object> response = new HashMap<String, Object>();//返回给小程序端需要的参数
            if (return_code.equals("SUCCESS") && return_code.equals(result_code)) {
                String prepay_id = (String) map.get("prepay_id");//返回的预付单信息
                response.put("nonceStr", nonce_str);
                response.put("package", "prepay_id=" + prepay_id);
                Long timeStamp = System.currentTimeMillis() / 1000;
                response.put("timeStamp", timeStamp + "");//这边要将返回的时间戳转化成字符串，不然小程序端调用wx.requestPayment方法会报签名错误
                //拼接签名需要的参数
                String stringSignTemp = "appId=" + WechatConfig.appid + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
                //再次签名，这个签名用于小程序端调用wx.requesetPayment方法
                String paySign = PayUtil.sign(stringSignTemp, WechatConfig.key, "utf-8").toUpperCase();

                response.put("paySign", paySign);
            }

            response.put("appid", WechatConfig.appid);
            response.put("payOrderId", payOrderId);
            System.out.println(response);
            System.out.println("======下程序微信支付结束" + payOrderId + "==============================");
            return DataResult.ok(response);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("======下程序微信支付结束" + payOrderId + "==============================");
        return null;

    }


    //获取随机字符串
    private String getRandomStringByLength(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    //获取IP
    private String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (!StringUtils.isEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            //多次反向代理后会有多个ip值，第一个ip才是真实ip
            int index = ip.indexOf(",");
            if (index != -1) {
                return ip.substring(0, index);
            } else {
                return ip;
            }
        }
        ip = request.getHeader("X-Real-IP");
        if (!StringUtils.isEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
            return ip;
        }
        return request.getRemoteAddr();
    }

}
